import { DomResult } from './types'

interface ClickOptions {
  timeout?: number
}

const DEFAULT_CLICK_OPTIONS: Required<ClickOptions> = {
  timeout: 5000, // 5秒 目标不存在等待时间
}



// 新增：支持复杂条件的等待函数
export const $waitFor = (
  conditionFn: () => boolean,
  options: ClickOptions = {}
): Promise<boolean> => {
  const { timeout } = { ...DEFAULT_CLICK_OPTIONS, ...options }

  return new Promise((resolve) => {
    // 先立即检查
    if (conditionFn()) {
      resolve(true)
      return
    }

    const observer = new MutationObserver(() => {
      if (conditionFn()) {
        observer.disconnect()
        resolve(true)
      }
    })

    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true, // 属性变化也可能影响条件
      characterData: true // 文本内容变化
    })

    setTimeout(() => {
      observer.disconnect()
      resolve(conditionFn()) // 最后检查一次
    }, timeout)
  })
}

export type SetInputOptions = {
  maxRetries?: number
  timeout?: number
  retryDelay?: number
}

const DEFAULT_OPTIONS: Required<SetInputOptions> = {
  maxRetries: 0, // 整个流程最大重试次数
  timeout: 5000, // 5秒 目标不存在等待时间
  retryDelay: 100, // 100毫秒 // 整个流程最大重试次数间隔时间
}

const wait = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms))

// 修改：接受选择器函数
const checkElementExists = (selectorFn: () => Element | null, timeout: number): Promise<Element | null> => {
  return new Promise((resolve) => {
    const startTime = Date.now()

    const check = () => {
      // 使用选择器函数查找元素
      const element = selectorFn()
      if (element) {
        resolve(element)
        return
      }

      if (Date.now() - startTime >= timeout) {
        resolve(null)
        return
      }

      setTimeout(check, 100)
    }

    check()
  })
}

const getElementValue = (element: Element): string => {
  const isInputOrTextarea = ['INPUT', 'TEXTAREA'].includes(element.tagName)
  return isInputOrTextarea
    ? (element as HTMLInputElement | HTMLTextAreaElement).value
    : (element.textContent || '')
}

const setElementValue = (element: Element, text: string): void => {
  const isInputOrTextarea = ['INPUT', 'TEXTAREA'].includes(element.tagName)

  if (isInputOrTextarea) {
    (element as HTMLInputElement | HTMLTextAreaElement).value = text
  } else {
    element.textContent = text
  }
}

const triggerInputEvent = (element: Element, lastValue: string): void => {
  const event = new Event('input', { bubbles: true })
    ; (event as any).simulated = true

  // 处理 React 的值跟踪器
  const tracker = (element as any)._valueTracker
  if (tracker) {
    tracker.setValue(lastValue)
  }

  element.dispatchEvent(event)
}

const changeReactInputValue = (element: Element, text: string): void => {
  const lastValue = getElementValue(element)
  setElementValue(element, text)
  triggerInputEvent(element, lastValue)
}

// 修改：支持选择器函数
export const $setInput = async (
  selectorFn: () => Element | null,
  text: string,
  options: SetInputOptions = {}
): Promise<DomResult> => {
  const { maxRetries, timeout, retryDelay } = { ...DEFAULT_OPTIONS, ...options }

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      // 1. 等待元素出现
      const element = await checkElementExists(selectorFn, timeout)

      // 2. 如果元素不存在
      if (!element) {
        if (attempt === maxRetries) {
          return DomResult.NOT_FOUND
        }
        await wait(retryDelay)
        continue
      }

      // 3. 尝试设置值
      try {
        changeReactInputValue(element, text)
      } catch (error) {
        if (attempt === maxRetries) {
          return DomResult.SET_ERROR
        }
        await wait(retryDelay)
        continue
      }

      // 4. 检查值是否设置成功
      await wait(50) // 等待一小段时间让值更新
      const currentValue = getElementValue(element)

      if (currentValue.includes(text)) {
        return DomResult.SUCCESS
      } else {
        if (attempt === maxRetries) {
          return DomResult.MAX_RETRIES_EXCEEDED
        }
        await wait(retryDelay)
      }

    } catch (error) {
      if (attempt === maxRetries) {
        return DomResult.SET_ERROR
      }
      await wait(retryDelay)
    }
  }

  return DomResult.MAX_RETRIES_EXCEEDED
}


// 新增：便捷函数用于字符串选择器设置输入值
export const $setInputBySelector = async (
  selector: string,
  text: string,
  options: SetInputOptions = {}
): Promise<DomResult> => {
  return $setInput(() => document.querySelector(selector), text, options)
}


// 设置输入值示例：
// await $setInput(() => document.querySelector('#username'), 'testuser')
// await $setInput(() => document.getElementById('email'), 'test@example.com')
// await $setInputBySelector('#username', 'testuser') // 向后兼容的字符串版本

// 复杂选择器示例：
// await $click(() => {
//   const buttons = document.querySelectorAll('button')
//   return Array.from(buttons).find(btn => btn.textContent === 'Submit')
// })

// await $setInput(() => {
//   const inputs = document.querySelectorAll('input[type="text"]')
//   return Array.from(inputs).find(input => input.placeholder === '请输入用户名')
// }, 'admin')

// 结果处理：
// if (result === DomResult.SUCCESS) {
//   console.log('操作成功')
// } else if (result === DomResult.NOT_FOUND) {
//   console.log('未找到目标元素')
// } else if (result === DomResult.CLICK_ERROR) {
//   console.log('点击失败')
// } else if (result === DomResult.SET_ERROR) {
//   console.log('设置输入值失败')
// } else if (result === DomResult.MAX_RETRIES_EXCEEDED) {
//   console.log('超过最大重试次数')
// }